﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Common.Logging;
using Framework.Message.SMS.CMPP.Commands;
using Framework.Core.Queue;
using System.Threading;
using Framework.Message.SMS.CommonLibrary;

namespace Framework.Message.SMS.CMPP
{
    public class CMPPClientClient : BaseClient<uint>, ISMSClient
    {
        #region 变量与属性
        /// <summary>
        /// 发命令套字节
        /// </summary>
        private Socket _SendCommandSocket = null;
        //private Socket _DeliveCommandSocket = null;
        private uint _LastMsgSequence = 0;

        /// <summary>
        /// 得到下一个排队序号
        /// </summary>
        /// <returns></returns>
        protected override uint NextSequence
        {
            get
            {
                lock (this)
                {
                    try
                    {
                        this._LastMsgSequence++;
                    }
                    catch (OverflowException e)
                    {
                        Logger.Error("序列号溢出。", e);
                        _LastMsgSequence = uint.MinValue;
                    }
                }
                return _LastMsgSequence;
            }
        }

        protected override uint CommandHeaderLength
        {
            get { return CommandHeader.HeaderLength; }
        }
        #region 线程
        /// <summary>
        /// 链接监测线程
        /// </summary>
        private BackgroundWorker _MonitoringThread = null;
        /// <summary>
        /// 发送命令线程
        /// </summary>
        private BackgroundWorker _SendCommandThread = null;
        /// <summary>
        /// 接收命令线程
        /// </summary>
        private BackgroundWorker _ReceiveCommandThread = null;

        #endregion

        #region 队列
        /// <summary>
        /// 待发送队列
        /// </summary>
        private IStatusQueue<string, Command, CommandInQueueStatus> _CommandQueue = new BaseStatusQueue<string, Command, CommandInQueueStatus>();
        ///// <summary>
        ///// 已发送队列
        ///// </summary>
        //private IStatusQueue<string, BaseCommand, CommandInQueueStatus> _SentCommandQueue = new BaseStatusQueue<string, BaseCommand, CommandInQueueStatus>();
        #endregion
        #endregion

        #region 事件
        /// <summary>
        /// 当登录前
        /// </summary>
        public event EventHandler<ConnectCommandEventArgs> Logining;
        protected void OnLogining(ConnectCommandEventArgs e)
        {
            if (Logining != null)
            {
                Logining(this, e);
            }
        }

        /// <summary>
        /// 当登录后
        /// </summary>
        public event EventHandler<ConnectRespCommandEventArgs> Logined;
        protected void OnLogined(ConnectRespCommandEventArgs e)
        {
            if (Logined != null)
            {
                Logined(this, e);
            }
        }

        public event EventHandler<EventArgs> Logouted;
        protected void OnLogouted(EventArgs e)
        {
            if (Logouted != null)
            {
                Logouted(this, e);
            }
        }
        #endregion

        #region 函数
        public CMPPClientClient(CMPPGatewaySetting gatewaySetting)
            : base(gatewaySetting)
        {
        }

        #region 私有函数
        private void SendCommand(Command command)
        {
            _SendCommandSocket.Send(command.ToBytes());
            this._LastActiveTime = DateTime.Now;
        }

        private void Login()
        {
            if (this._IsLogin)
            {
                return;
            }
            try
            {
                ConnectCommand command = CommandFactory.GetNewCommand<ConnectCommand>(this.NextSequence);
                if (command != null)
                {
                    command.SourceAddr = GatewaySetting.LoginName;
                    command.Password = GatewaySetting.Password;
                    OnLogining(new ConnectCommandEventArgs());
                    SendCommand(command);
                    Logger.Debug("发送登录命令。");
                }
            }
            catch (Exception ex)
            {
                //发送出错
                Logger.Error("登录网关异常：", ex);
                throw ex;
            }
            DateTime t1 = DateTime.Now;
            Logger.Debug("等待登录命令回复。");
            while (!this._IsLogin)
            {
                byte[] rbuf = new Byte[50];
                int l;
                try
                {
                    l = this._SendCommandSocket.Receive(rbuf);
                    if (l >= 29)
                    {
                        if (ByteIntConvert.Bytes2UInt(rbuf, 4) == (uint)CMPPCommandType.Connect_Resp)
                        {
                            //ConnectRespCommand resp = new ConnectRespCommand(rbuf);
                            //ConnectRespCommandEventArgs arg = new ConnectRespCommandEventArgs();
                            //arg.RespErrorCode = resp.Result;
                            //OnLogined(arg);
                            //if (resp.Result == ErrorCode.Success)
                            //{
                            //    this._IsLogin = true;
                            //    Logger.Debug("登录成功。");
                            //}
                            //else
                            //{
                            //    this._IsLogin = false;
                            //    Logger.Debug(string.Format("登录失败。错误代码", resp.Result));
                            //}
                            //break;
                        }
                    }
                    this._LastActiveTime = DateTime.Now;  //更新当前最后成功收发套接字的时间
                }
                catch (Exception ex)
                {
                    Logger.Error("登录网关异常：", ex);
                    throw ex;
                }
                System.TimeSpan t = DateTime.Now - t1;
                if (t.TotalSeconds > 10)
                {
                    break;
                }
                Thread.Sleep(50);
            }
        }

        private void Ping()
        {
            ActiveTestCommand command = CommandFactory.GetNewCommand(CMPPCommandType.Active_Test, this.NextSequence) as ActiveTestCommand;
            if (command != null)
            {
                this.SendCommand(command);
                this.Logger.Debug("发送了Ping命令。");
                this._CommandQueue.Add(command.Header.SequenceNumber.ToString(), command, CommandInQueueStatus.Sent);
                Logger.Debug(string.Format("命令【{0}】进入已发送队列中。", command.Header.SequenceNumber.ToString()));
                this._LastPingTime = DateTime.Now;
            }
        }

        #region 线程处理函数

        #endregion
        #endregion

        #endregion

        #region ISMSClient Members

        public void Start()
        {
            if (!this._IsStarted)
            {
                //if (_GatewaySetting == null)
                //{
                //    Logger.Error("请先配置模块。");
                //    throw new ApplicationException("请先配置模块。");
                //}

                //Logger.Debug("准备开启服务。");
                //try
                //{
                //    this._SendCommandSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //    IPHostEntry ipHE = Dns.GetHostEntry(_GatewaySetting.ServiceIP);
                //    IPEndPoint ipEP = new IPEndPoint(ipHE.AddressList[0], _GatewaySetting.MTPort);
                //    this._SendCommandSocket.Connect(ipEP);
                //}
                //catch (System.Exception ex)
                //{
                //    Logger.Error("Socket Error。", ex);
                //    throw ex;
                //}
                //Logger.Debug("Socket连接成功。");
                //this.Login();
                //this.ThreadsStart();
                //this._IsStarted = true;
            }
        }

        public void Stop()
        {
        }
        #endregion
    }
}
